package com.nfc.lock.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.nfc.lock.common.constant.Constants;
import com.nfc.lock.common.exception.BusinessException;
import com.nfc.lock.common.result.ResultCode;
import com.nfc.lock.dto.request.RoomAddRequest;
import com.nfc.lock.dto.response.LockListVO;
import com.nfc.lock.dto.response.MapRoomVO;
import com.nfc.lock.dto.response.RoomDetailVO;
import com.nfc.lock.entity.NfcLock;
import com.nfc.lock.entity.PowerRoom;
import com.nfc.lock.entity.Region;
import com.nfc.lock.entity.User;
import com.nfc.lock.mapper.NfcLockMapper;
import com.nfc.lock.mapper.PowerRoomMapper;
import com.nfc.lock.mapper.RegionMapper;
import com.nfc.lock.security.SecurityUtils;
import com.nfc.lock.service.IPowerRoomService;
import com.nfc.lock.service.IUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * Power room service implementation.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PowerRoomServiceImpl extends ServiceImpl<PowerRoomMapper, PowerRoom> implements IPowerRoomService {

    private final PowerRoomMapper powerRoomMapper;
    private final RegionMapper regionMapper;
    private final NfcLockMapper nfcLockMapper;
    private final IUserService userService;
    @Override
    public IPage<RoomDetailVO> getRoomList(Integer pageNum, Integer pageSize, String keyword, Long regionId) {
        Page<RoomDetailVO> page = new Page<>(pageNum, pageSize);
        IPage<RoomDetailVO> result = powerRoomMapper.selectRoomPage(page, keyword, regionId);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRoom(RoomAddRequest request) {
        Region region = regionMapper.selectById(request.getRegionId());
        if (region == null) {
            throw new BusinessException(ResultCode.REGION_NOT_EXIST);
        }

        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (!userService.checkPermission(currentUserId, region.getRegionId())) {
            throw new BusinessException(ResultCode.FORBIDDEN);
        }

        PowerRoom room = new PowerRoom();
        room.setRoomName(request.getRoomName());
        room.setRegionId(request.getRegionId());
        room.setLongitude(request.getLongitude());
        room.setLatitude(request.getLatitude());
        room.setAddress(request.getAddress());
        room.setCreateBy(currentUserId);

        powerRoomMapper.insert(room);
        log.info("Power room created successfully: {}", room.getRoomName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRoom(Long roomId, RoomAddRequest request) {
        PowerRoom room = powerRoomMapper.selectById(roomId);
        if (room == null) {
            throw new BusinessException(ResultCode.ROOM_NOT_EXIST);
        }

        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (!userService.checkPermission(currentUserId, room.getRegionId())) {
            throw new BusinessException(ResultCode.FORBIDDEN);
        }

        room.setRoomName(request.getRoomName());
        room.setRegionId(request.getRegionId());
        room.setLongitude(request.getLongitude());
        room.setLatitude(request.getLatitude());
        room.setAddress(request.getAddress());

        powerRoomMapper.updateById(room);
        log.info("Power room updated successfully: {}", roomId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRoom(Long roomId) {
        PowerRoom room = powerRoomMapper.selectById(roomId);
        if (room == null) {
            throw new BusinessException(ResultCode.ROOM_NOT_EXIST);
        }

        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (!userService.checkPermission(currentUserId, room.getRegionId())) {
            throw new BusinessException(ResultCode.FORBIDDEN);
        }

        if (nfcLockMapper.countByRoomId(roomId) > 0) {
            throw new BusinessException(ResultCode.ROOM_HAS_LOCKS);
        }

        powerRoomMapper.deleteById(roomId);
        log.info("Power room deleted successfully: {}", roomId);
    }

    @Override
    public RoomDetailVO getRoomDetail(Long roomId) {
        PowerRoom room = powerRoomMapper.selectById(roomId);
        if (room == null) {
            throw new BusinessException(ResultCode.ROOM_NOT_EXIST);
        }

        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (!userService.checkPermission(currentUserId, room.getRegionId())) {
            throw new BusinessException(ResultCode.FORBIDDEN);
        }

        RoomDetailVO detail = new RoomDetailVO();
        detail.setRoomId(room.getRoomId());
        detail.setRoomName(room.getRoomName());
        detail.setRegionId(room.getRegionId());
        Region region = regionMapper.selectById(room.getRegionId());
        detail.setRegionName(region != null ? region.getRegionName() : null);
        detail.setLongitude(room.getLongitude());
        detail.setLatitude(room.getLatitude());
        detail.setAddress(room.getAddress());
        detail.setCreateTime(room.getCreateTime());

        Page<LockListVO> page = new Page<>(1, 200);
        IPage<LockListVO> lockPage = nfcLockMapper.selectLockPage(page, null, roomId, null, null);
        List<LockListVO> locks = lockPage.getRecords();
        detail.setLocks(locks);

        int total = locks.size();
        int malfunction = (int) locks.stream()
                .filter(lockVO -> lockVO.getIsDamaged() != null && lockVO.getIsDamaged() == 1)
                .count();
        int open = (int) locks.stream()
                .filter(lockVO -> (lockVO.getIsDamaged() == null || lockVO.getIsDamaged() == 0)
                        && lockVO.getLockStatus() != null && lockVO.getLockStatus() == 1)
                .count();

        detail.setLockCount(total);
        detail.setMalfunctionLockCount(malfunction);
        detail.setOpenLockCount(open);
        int status = malfunction > 0 ? 2 : (open > 0 ? 1 : 0);
        detail.setStatus(status);

        return detail;
    }

    @Override
    public List<MapRoomVO> getMapRooms(Long regionId, Integer status, String keyword) {
        log.info("=== HTTP请求日志 === 开始处理地图配电室查询请求: regionId={}, status={}, keyword={}", regionId, status, keyword);
        
        Long currentUserId = SecurityUtils.getCurrentUserId();
        User currentUser = userService.getById(currentUserId);
        if (currentUser == null) {
            log.error("=== 业务逻辑日志 === 用户不存在: userId={}", currentUserId);
            throw new BusinessException(ResultCode.USER_NOT_EXIST);
        }
        
        log.info("=== 业务逻辑日志 === 当前用户信息: userId={}, username={}, roleType={}, regionId={}", 
                currentUser.getUserId(), currentUser.getUsername(), currentUser.getRoleType(), currentUser.getRegionId());

        List<Long> accessibleRegionIds = resolveAccessibleRegionIds(currentUser);
        List<Long> targetRegionIds = accessibleRegionIds;
        log.info("=== 业务逻辑日志 === 用户可访问的区域ID列表: {}", accessibleRegionIds);

        if (regionId != null) {
            log.info("=== 业务逻辑日志 === 检查用户对指定区域的权限: targetRegionId={}", regionId);
            if (!userService.checkPermission(currentUserId, regionId)) {
                log.warn("=== 业务逻辑日志 === 用户无权限访问指定区域: userId={}, targetRegionId={}", currentUserId, regionId);
                return Collections.emptyList();
            }
            targetRegionIds = resolveRegionScope(regionId);
            log.info("=== 业务逻辑日志 === 解析后的目标区域ID列表: {}", targetRegionIds);
        }

        if (targetRegionIds != null && targetRegionIds.isEmpty()) {
            log.info("=== 业务逻辑日志 === 目标区域ID列表为空，返回空结果");
            return Collections.emptyList();
        }

        // 构建查询条件
        var queryWrapper = Wrappers.<PowerRoom>lambdaQuery();
        if (targetRegionIds != null) {
            queryWrapper.in(PowerRoom::getRegionId, targetRegionIds);
        }
        if (keyword != null && !keyword.trim().isEmpty()) {
            queryWrapper.like(PowerRoom::getRoomName, keyword.trim());
            log.info("=== SQL查询日志 === 添加关键字搜索条件: keyword={}", keyword.trim());
        }
        
        log.info("=== SQL查询日志 === 开始查询配电室列表，查询条件: targetRegionIds={}, keyword={}", targetRegionIds, keyword);
        List<PowerRoom> rooms = powerRoomMapper.selectList(queryWrapper);
        log.info("=== 数据库返回结果 === 查询到配电室数量: {}", rooms.size());

        if (rooms.isEmpty()) {
            log.info("=== 业务逻辑日志 === 未查询到符合条件的配电室，返回空结果");
            return Collections.emptyList();
        }

        List<Long> roomIds = rooms.stream()
                .map(PowerRoom::getRoomId)
                .collect(Collectors.toList());
        log.info("=== 业务逻辑日志 === 提取配电室ID列表: {}", roomIds);

        Map<Long, List<NfcLock>> locksByRoom = Collections.emptyMap();
        if (!roomIds.isEmpty()) {
            log.info("=== SQL查询日志 === 开始查询配电室对应的锁信息: roomIds={}", roomIds);
            List<NfcLock> locks = nfcLockMapper.selectList(
                    Wrappers.<NfcLock>lambdaQuery()
                            .in(NfcLock::getRoomId, roomIds)
            );
            log.info("=== 数据库返回结果 === 查询到锁数量: {}", locks.size());
            locksByRoom = locks.stream()
                    .collect(Collectors.groupingBy(NfcLock::getRoomId));
            log.info("=== 业务逻辑日志 === 按配电室分组的锁信息: {}", 
                    locksByRoom.entrySet().stream()
                            .collect(Collectors.toMap(
                                    Map.Entry::getKey, 
                                    entry -> entry.getValue().size()
                            )));
        }

        List<MapRoomVO> result = new ArrayList<>();
        for (PowerRoom room : rooms) {
            List<NfcLock> roomLocks = locksByRoom.getOrDefault(room.getRoomId(), Collections.emptyList());
            int totalLocks = roomLocks.size();
            int malfunctionCount = (int) roomLocks.stream()
                    .filter(lock -> lock.getIsDamaged() != null && lock.getIsDamaged() == 1)
                    .count();
            int openCount = (int) roomLocks.stream()
                    .filter(lock -> (lock.getIsDamaged() == null || lock.getIsDamaged() == 0)
                            && lock.getLockStatus() != null && lock.getLockStatus() == Constants.LockStatus.OPEN)
                    .count();
            int roomStatus = malfunctionCount > 0 ? 2 : (openCount > 0 ? 1 : 0);
            
            log.debug("=== 业务逻辑日志 === 配电室状态计算: roomId={}, roomName={}, totalLocks={}, openCount={}, malfunctionCount={}, roomStatus={}", 
                    room.getRoomId(), room.getRoomName(), totalLocks, openCount, malfunctionCount, roomStatus);

            if (status != null && !status.equals(roomStatus)) {
                log.debug("=== 业务逻辑日志 === 配电室状态不匹配过滤条件，跳过: roomId={}, roomStatus={}, filterStatus={}", 
                        room.getRoomId(), roomStatus, status);
                continue;
            }

            MapRoomVO vo = new MapRoomVO();
            vo.setRoomId(room.getRoomId());
            vo.setRoomName(room.getRoomName());
            vo.setLongitude(room.getLongitude() != null ? room.getLongitude().doubleValue() : null);
            vo.setLatitude(room.getLatitude() != null ? room.getLatitude().doubleValue() : null);
            vo.setAddress(room.getAddress());
            vo.setLockCount(totalLocks);
            vo.setOpenCount(openCount);
            vo.setMalfunctionCount(malfunctionCount);
            vo.setStatus(roomStatus);
            result.add(vo);
            
            log.debug("=== 业务逻辑日志 === 添加配电室到结果集: roomId={}, roomName={}, coordinates=({}, {})", 
                    room.getRoomId(), room.getRoomName(), vo.getLongitude(), vo.getLatitude());
        }

        log.info("=== 数据库返回结果 === 最终返回配电室数量: {}", result.size());
        log.info("=== HTTP请求日志 === 地图配电室查询请求处理完成: regionId={}, status={}, keyword={}, resultCount={}", 
                regionId, status, keyword, result.size());
        return result;
    }

    private List<Long> resolveAccessibleRegionIds(User user) {
        if (user.getRoleType() != null && user.getRoleType() == Constants.RoleType.SUPER_ADMIN) {
            return null;
        }

        Long regionId = user.getRegionId();
        if (regionId == null) {
            return Collections.emptyList();
        }

        Region userRegion = regionMapper.selectById(regionId);
        if (userRegion == null || userRegion.getLevelPath() == null) {
            return Collections.singletonList(regionId);
        }

        return regionMapper.selectByLevelPathLike(userRegion.getLevelPath()).stream()
                .map(Region::getRegionId)
                .collect(Collectors.toList());
    }

    private List<Long> resolveRegionScope(Long regionId) {
        Region region = regionMapper.selectById(regionId);
        if (region == null) {
            return Collections.emptyList();
        }
        if (region.getLevelPath() == null) {
            return Collections.singletonList(regionId);
        }
        return regionMapper.selectByLevelPathLike(region.getLevelPath()).stream()
                .map(Region::getRegionId)
                .collect(Collectors.toList());
    }

}
